package com.me.bbs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.me.bbs.common.SessionUtils;
import com.me.bbs.dto.ForumDTO;
import com.me.bbs.entity.*;
import com.me.bbs.exceptions.NotExistException;
import com.me.bbs.mapper.ForumMapper;
import com.me.bbs.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lm
 * @since 2023-01-11
 */
@Service
public class ForumServiceImpl extends ServiceImpl<ForumMapper, Forum> implements IForumService {
    @Resource
    private ForumMapper forumMapper;
    @Resource
    private IForumFollowingService forumFollowingService;

    @Resource
    private IPostService postService;
    @Resource
    private IPostLikeService postLikeService;
    @Resource
    private ICommentService commentService;
    @Resource
    private IViewRecordService viewRecordService;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ForumDTO getForumDetail(Long id) {

        Long uid = (Long) SessionUtils.getAttribute("user");
        ForumDTO forumDTO = forumMapper.selectForumDetail(id);
        if(forumDTO == null)
            throw new NotExistException();
        boolean isFollowed = forumFollowingService.lambdaQuery()
                .eq(ForumFollowing::getUser, uid)
                .eq(ForumFollowing::getForum, forumDTO.getId())
                .exists();
        forumDTO.setIsFollowed(isFollowed);
        return forumDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> getTodayStatistics(Long forumId) {
        Map<String ,Object> resMap = new HashMap<>();
        LocalDateTime dateTime =  LocalDateTime.now().withSecond(0).withHour(0).withMinute(0);
        Long postCount = postService.lambdaQuery().eq(Post::getForum, forumId)
                .ge(Post::getCreateTime, dateTime)
                .count();
        resMap.put("postCount", postCount);
        Long followCount = forumFollowingService.lambdaQuery()
                .eq(ForumFollowing::getForum,forumId)
                .ge(ForumFollowing::getCreateAt,dateTime)
                .count();
        resMap.put("followCount", followCount);
        Long viewCount = viewRecordService.lambdaQuery().
                exists("select 1 from post p where p.post_id = post and p.forum = {0}", forumId)
                .ge(ViewRecord::getViewTime, dateTime)
                .count();
        resMap.put("viewCount", viewCount);
        Long commentCount = commentService.lambdaQuery()
                .eq(Comment::getForum, forumId)
                .ge(Comment::getCreateAt, dateTime)
                .count();
        resMap.put("commentCount", commentCount);
        Long likeCount = postLikeService.lambdaQuery()
                . exists("select 1 from post p where p.post_id = post and p.forum = {0}", forumId)
                .ge(PostLike::getCreateTime, dateTime)
                .count();
        resMap.put("likeCount", likeCount);
        return resMap;
    }

    @Override
    public Map<String, Object> getWeekStatistics(Long forumId) {
        LocalDateTime dateTime =  LocalDateTime.now().withSecond(0).withHour(0).withMinute(0);
        List<LocalDateTime> timeList = new ArrayList<>();
        timeList.add(0, dateTime);
        for (int i = 0; i < 6; i++) {
            dateTime = dateTime.plusDays(-1L);
            timeList.add(0,dateTime);
        }
        Map<String ,Object> listMap = new HashMap<>();
        List<Long> postCountList = new ArrayList<>();
        List<Long> followCountList = new ArrayList<>();
        List<Long> viewCountList = new ArrayList<>();
        List<Long> commentCountList = new ArrayList<>();
        List<Long> likeCountList = new ArrayList<>();
        listMap.put("postCountList",postCountList);
        listMap.put("followCountList",followCountList);
        listMap.put("viewCountList",viewCountList);
        listMap.put("commentCountList",commentCountList);
        listMap.put("likeCountList",likeCountList);
        timeList.forEach((t)->{

            Long postCount = postService.lambdaQuery().eq(Post::getForum, forumId)
                    .ge(Post::getCreateTime, t)
                    .lt(Post::getCreateTime, t.plusDays(1))
                    .count();
            postCountList.add(postCount);
            Long followCount = forumFollowingService.lambdaQuery()
                    .eq(ForumFollowing::getForum,forumId)
                    .ge(ForumFollowing::getCreateAt,t)
                    .lt(ForumFollowing::getCreateAt,t.plusDays(1))
                    .count();
            followCountList.add(followCount);
            Long viewCount = viewRecordService.lambdaQuery().
                    exists("select 1 from post p where p.post_id = post and p.forum = {0}", forumId)
                    .ge(ViewRecord::getViewTime, t)
                    .lt(ViewRecord::getViewTime,t.plusDays(1))
                    .count();
            viewCountList.add(viewCount);
            Long commentCount = commentService.lambdaQuery()
                    .eq(Comment::getForum, forumId)
                    .ge(Comment::getCreateAt, t)
                    .lt(Comment::getCreateAt, t.plusDays(1))
                    .count();
            commentCountList.add( commentCount);
            Long likeCount = postLikeService.lambdaQuery()
                    . exists("select 1 from post p where p.post_id = post and p.forum = {0}", forumId)
                    .ge(PostLike::getCreateTime, t)
                    .lt(PostLike::getCreateTime, t.plusDays(1))
                    .count();
            likeCountList.add(likeCount);
        });
        return listMap;
    }




}
